using System;
using System.Collections.Generic;
using System.Linq;
using HengTong.Model;
using HengTong.Model.Db.Hr;
using HengTong.Model.Db.Hr.Attendance;
using HengTong.Model.Extension;
using HengTong.ViewModel.Hr.SysAttendanceShiftGroupVms;
using Microsoft.EntityFrameworkCore;
using TiaoTaoHelper.Extension.String;
using TiaoTaoHelper.Wtm.Models;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;

namespace HengTong.ViewModel.Hr.SysAttendanceRecordVms;

public partial class
    SysAttendanceRecordByPersonListVm : BaseListVm<SysAttendanceShiftByPersonView, SysAttendanceRecordByPersonSearcher>
{
    protected override IEnumerable<IGridColumn<SysAttendanceShiftByPersonView>> InitGridHeader()
    {
        return new List<GridColumn<SysAttendanceShiftByPersonView>>
        {
            this.MakeGridHeader(x => x.Name),
            this.MakeGridHeader(x => x.ID),
            this.MakeGridHeader(x => x.StaffNo),
            this.MakeGridHeader(x => x.Records),
            this.MakeGridHeaderAction(width: 200)
        };
    }

    public override IOrderedQueryable<SysAttendanceShiftByPersonView> GetSearchQuery()
    {
        DateOnly start = Searcher.ShiftDate?.GetStartTime() != null
            ? DateOnly.FromDateTime(Searcher.ShiftDate.GetStartTime().Value)
            : DateOnly.FromDateTime(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1));
        DateOnly end = Searcher.ShiftDate?.GetEndTime() != null
            ? DateOnly.FromDateTime(Searcher.ShiftDate.GetEndTime().Value)
            : DateOnly.FromDateTime(new DateTime(DateTime.Now.AddMonths(1).Year, DateTime.Now.AddMonths(1).Month, 1)
                .AddDays(-1));

        var query = DC.Set<SysPerson>()
            .CheckEqual(Searcher.Name, x => x.Name)
            .CheckEqual(Searcher.OrgId, x => x.OrgId)
            .CheckEqual(Searcher.StaffNo, x => x.StaffNo)
            .Where(e => e.State == PersonState.在职 && !e.StaffNo.StartsWith("-"))
            .Where(x => x.GetType() == typeof(SysPerson))
            .CheckEqual(Searcher.PersonId, x => x.ID);

        // 优化部门查询：查询指定部门及其子部门
        if (Searcher.GroupId.HasValue)
        {
            var targetGroup = DC.Set<SysGroup>().FirstOrDefault(g => g.ID == Searcher.GroupId.Value);
            if (targetGroup != null)
            {
                // 获取目标部门及其所有子部门的ID
                var groupIds = DC.Set<SysGroup>()
                    .Where(g => g.GroupCode.StartsWith(targetGroup.GroupCode))
                    .Select(g => g.ID)
                    .ToList();

                query = query.Where(x => groupIds.Contains(x.GroupId.Value));
            }
        }

        return query.Select(x => new SysAttendanceShiftByPersonView
            {
                ID = x.ID,
                Name = x.Name,
                StaffNo = x.StaffNo,
                GroupName = x.Group.GroupName,
                GroupId = x.GroupId,
                Records = DC.Set<SysAttendanceRecord>()
                    .Include(e => e.AttendanceShiftGroup)
                    .ThenInclude(e => e.Shifts)
                    .ThenInclude(e => e.Shift)
                    .Where(r => r.PersonId == x.ID)
                    .Where(r => r.ShiftDate >= start && r.ShiftDate <= end)
                    .Select(e => new SysAttendanceRecordView()
                    {
                        ID = e.ID,
                        PersonName = e.Person.Name,
                        ShiftType = e.ShiftType,
                        ScheduleType = e.ScheduleType,
                        Status = e.Status,
                        Remark = e.Remark,
                        SubstitutePersonName = e.SubstitutePerson.Name,
                        AttendanceResult = e.AttendanceResult,
                        LateMinutes = e.LateMinutes,
                        EarlyLeaveMinutes = e.EarlyLeaveMinutes,
                        WorkMinutes = e.WorkMinutes,
                        MissingPunchCount = e.MissingPunchCount,
                        IsAbnormal = e.IsAbnormal,
                        ShiftDate = e.ShiftDate,
                        AttendanceShiftGroup = e.AttendanceShiftGroup,
                        AttendanceShiftGroupName = e.AttendanceShiftGroup.Name,
                        AttendanceShiftGroupId = e.AttendanceShiftGroupId,
                        StartTime = e.StartTime,
                        EndTime = e.EndTime,
                        UpdateTime = e.UpdateTime,
                        UpdateBy = e.UpdateBy
                    })
                    .OrderBy(e => e.ShiftDate)
                    .ToList()
            })
            .OrderBy(x => x.StaffNo);
    }

    public override void AfterDoSearcher()
    {
        foreach (var item in EntityList)
        {
            foreach (var record in item.Records)
            {
                UpdateView(record);
                record.AttendanceShiftGroup = null;
                record.UpdateBy = Wtm.FormatUsername(record.UpdateBy);
            }
        }

        base.AfterDoSearcher();
    }


    private void UpdateView(SysAttendanceRecordView view)
    {
        var group = view.AttendanceShiftGroup;
        view.ShiftDetails = new List<ShiftDetailInfo>();

        if (group.Type == ShiftGroupType.行政班)
        {
            if (!group.SchedulePattern.TryJsonParse(out List<string> days))
            {
                MSD.AddModelError(" ", "排班模式格式错误");
                return;
            }

            var dayOfWeek = view.ShiftDate.DayOfWeek;
            var isWorkDay = days.Contains(dayOfWeek switch
            {
                DayOfWeek.Monday => "星期一",
                DayOfWeek.Tuesday => "星期二",
                DayOfWeek.Wednesday => "星期三",
                DayOfWeek.Thursday => "星期四",
                DayOfWeek.Friday => "星期五",
                DayOfWeek.Saturday => "星期六",
                DayOfWeek.Sunday => "星期天",
                _ => ""
            });

            if (isWorkDay)
            {
                // 获取所有班次并按时间排序
                var shifts = group.Shifts
                    .Select(s => s.Shift)
                    .Where(s => s != null)
                    .OrderBy(s => s.WorkStartTime)
                    .ToList();

                if (shifts.Any())
                {
                    // 填充多班次详情
                    foreach (var shift in shifts)
                    {
                        view.ShiftDetails.Add(new ShiftDetailInfo
                        {
                            ShiftName = shift.Name,
                            DisplayColor = shift.DisplayColor,
                            WorkStartTime = shift.WorkStartTime,
                            WorkEndTime = shift.WorkEndTime,
                            StandardWorkMinutes = shift.StandardWorkMinutes,
                            AttendanceDays = shift.AttendanceDays
                        });
                    }

                    // 设置汇总信息(用于兼容旧代码)
                    var firstShift = shifts.First();
                    var lastShift = shifts.Last();

                    view.ShiftInfo = shifts.Count > 1
                        ? $"{string.Join(" + ", shifts.Select(s => s.Name))}"
                        : firstShift.Name;

                    view.DisplayColor = firstShift.DisplayColor;
                    view.WorkStartTime = firstShift.WorkStartTime;
                    view.WorkEndTime = lastShift.WorkEndTime;
                    view.StandardWorkMinutes = shifts.Sum(s => s.StandardWorkMinutes);
                    view.AttendanceDays = shifts.Sum(s => s.AttendanceDays);
                }
            }
            else
            {
                view.ShiftInfo = "休";
                view.DisplayColor = "";
            }
        }
        else if (group.Type == ShiftGroupType.三班倒)
        {
            // 三班倒逻辑保持不变,添加ShiftDetails填充
            if (!group.SchedulePattern.TryJsonParse(out ShiftGroupDayInfo info))
            {
                MSD.AddModelError(" ", "排班模式格式错误");
                return;
            }

            if (info.WorkDate == null)
            {
                MSD.AddModelError(" ", "排班模式错误,缺少排班起始日期");
                return;
            }

            var daysDiff = (view.ShiftDate.ToDateTime(TimeOnly.MinValue) -
                            info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days;
            var cycleIndex = ((daysDiff % 3) + 3) % 3;

            SysAttendanceShiftTag currentTag = cycleIndex switch
            {
                0 => SysAttendanceShiftTag.A,
                1 => SysAttendanceShiftTag.B,
                2 => SysAttendanceShiftTag.休,
                _ => throw new Exception("计算三班倒错误")
            };

            var shiftAndGroup = group.Shifts.FirstOrDefault(e => e.Tag == currentTag);
            if (shiftAndGroup?.Shift != null)
            {
                var shift = shiftAndGroup.Shift;
                SetSingleShiftView(view, shift);
            }
            else
            {
                SetRestDayView(view);
            }
        }
        else if (group.Type == ShiftGroupType.两班倒)
        {
            // 两班倒逻辑类似
            if (!group.SchedulePattern.TryJsonParse(out ShiftGroupDayInfo info))
            {
                MSD.AddModelError(" ", "排班模式格式错误");
                return;
            }

            if (info.WorkDate == null)
            {
                MSD.AddModelError(" ", "排班模式错误,缺少排班起始日期");
                return;
            }

            var daysDiff = (view.ShiftDate.ToDateTime(TimeOnly.MinValue) -
                            info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days;
            var cycleIndex = ((daysDiff % 2) + 2) % 2;

            SysAttendanceShiftTag currentTag = cycleIndex == 0
                ? SysAttendanceShiftTag.A
                : SysAttendanceShiftTag.休;

            var shiftAndGroup = group.Shifts.FirstOrDefault(e => e.Tag == currentTag);
            if (shiftAndGroup?.Shift != null)
            {
                var shift = shiftAndGroup.Shift;
                SetSingleShiftView(view, shift);
            }
            else
            {
                SetRestDayView(view);
            }
        }
        else if (group.Type == ShiftGroupType.上一休二)
        {
            // 上一休二逻辑类似
            if (!group.SchedulePattern.TryJsonParse(out ShiftGroupDayInfo info))
            {
                MSD.AddModelError(" ", "排班模式格式错误");
                return;
            }

            if (info.WorkDate == null)
            {
                MSD.AddModelError(" ", "排班模式错误,缺少排班起始日期");
                return;
            }

            var daysDiff = (view.ShiftDate.ToDateTime(TimeOnly.MinValue) -
                            info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days;
            var cycleIndex = ((daysDiff % 3) + 3) % 3;

            SysAttendanceShiftTag currentTag = cycleIndex switch
            {
                0 => SysAttendanceShiftTag.A,
                1 => SysAttendanceShiftTag.休1,
                2 => SysAttendanceShiftTag.休2,
                _ => throw new Exception("计算上一休二错误")
            };

            var shiftAndGroup = group.Shifts.FirstOrDefault(e => e.Tag == currentTag);
            if (shiftAndGroup?.Shift != null)
            {
                var shift = shiftAndGroup.Shift;
                SetSingleShiftView(view, shift);
            }
            else
            {
                SetRestDayView(view);
            }
        }
    }

// 辅助方法:设置单班次视图
    private void SetSingleShiftView(SysAttendanceRecordView view, SysAttendanceShift shift)
    {
        view.ShiftInfo = shift.Name;
        view.DisplayColor = shift.DisplayColor;
        view.WorkStartTime = shift.WorkStartTime;
        view.WorkEndTime = shift.WorkEndTime;
        view.StandardWorkMinutes = shift.StandardWorkMinutes;
        view.AttendanceDays = shift.AttendanceDays;

        view.ShiftDetails.Add(new ShiftDetailInfo
        {
            ShiftName = shift.Name,
            DisplayColor = shift.DisplayColor,
            WorkStartTime = shift.WorkStartTime,
            WorkEndTime = shift.WorkEndTime,
            StandardWorkMinutes = shift.StandardWorkMinutes,
            AttendanceDays = shift.AttendanceDays
        });
    }

// 辅助方法:设置休息日视图
    private void SetRestDayView(SysAttendanceRecordView view)
    {
        view.ShiftInfo = "休";
        view.DisplayColor = "";
        view.ShiftDetails = new List<ShiftDetailInfo>();
    }
}

public class SysAttendanceShiftByPersonView : TopBasePoco
{
    public Guid ID { get; set; }

    public string Name { get; set; }

    public string StaffNo { get; set; }

    public List<SysAttendanceRecordView> Records { get; set; }

    public string GroupName { get; set; }

    public Guid? GroupId { get; set; }
}